import pandas as pd
import random
from numbers import Real
from typing import Union, Optional, Sequence


from collections import defaultdict
import pandas as pd


class DataProcessor:
    def __init__(self, base_data, project_info, rules):
        """
        初始化数据处理器

        :param base_data: 原始数据（如 DataFrame）
        :param project_info: 项目基础信息字典
        :param rules: 字段规则字典 {字段名: 规则}
        """
        self.base_data = base_data
        self.project_info = project_info
        self.rules = rules
        self.context = {
        'global': {},
        'sheets': defaultdict(dict),
        }
        self.type_handlers = {
            'string': self._handle_string,
            'list_vertical': self._handle_list_vertical,
            'list_horizontal': self._handle_list_horizontal,
            'date': self._handle_date,
        }
        


    def process_dataframe(self, df):
        """
        处理整个 DataFrame，生成 processed_values 列
        
        :param df: 原始 DataFrame，包含 ['工作表名称', '内容名称', '单元格编号']
        :return: 新增一列 'processed_values'
        """

        # 自动处理依赖顺序字段排序
        dependency_order = [
            # JS101相关字段
            '设计坐标1(X)', '设计坐标1(Y)',
            'X轴偏位1', 'Y轴偏位1',
            '设计坐标2(X)', '设计坐标2(Y)',
            'X轴偏位2', 'Y轴偏位2',
            '设计坐标3(X)', '设计坐标3(Y)',
            'X轴偏位3', 'Y轴偏位3',
            '设计坐标4(X)', '设计坐标4(Y)',
            'X轴偏位4', 'Y轴偏位4',
            '实际坐标1(X)', '实际坐标1(Y)',
            '实际坐标2(X)', '实际坐标2(Y)',
            '实际坐标3(X)', '实际坐标3(Y)',
            '实际坐标4(X)', '实际坐标4(Y)',
            # JS103(1)相关字段
            '设计高程(1)','设计高程(2)',
            '设计高程(3)','设计高程(4)',
            '设计高程(5)','高差(1)',
            '高差(2)','高差(3)',
            '高差(4)','高差(5)',
            '实测高程(1)','实测高程(2)',
            '实测高程(3)','实测高程(4)',
            '实测高程(5)',
            #
        ]

        def get_sort_key(field):
            try:
                return dependency_order.index(field)
            except ValueError:
                return len(dependency_order) + 1

        df = df.copy()
        df['sort_key'] = df['内容名称'].apply(get_sort_key)
        df = df.sort_values('sort_key').drop('sort_key', axis=1)

        df['processed_values'] = df.apply(self._process_row, axis=1)
        return df

    def _process_row(self, row):
        """
        处理单行数据，调用对应字段的 handler 并进行格式化输出

        :param row: DataFrame 中的一行数据
        :return: 处理后的值对象
        """
        sheet_name = row.get('工作表名称', 'default')
        content_name = row.get('内容名称')
        rule_key = (sheet_name, content_name)
        rule = self.rules.get(rule_key) or self.rules.get(content_name)
        
        if not rule:
            return self._default_response(content_name)

        try:
            params = {
                'project': self.project_info,
                'meta': self.base_data,
                'extra': {'sheet': sheet_name},
                'context': self.context
            }

            if 'dependencies' in rule:
                resolved_deps = {
                    dep: self._resolve_dependency(dep, sheet_name)
                    for dep in rule['dependencies']
                }
                params['resolved_deps'] = resolved_deps

            raw_value = rule['handler'](params)
            data_type = rule.get('data_type', 'string')
            handler = self.type_handlers.get(data_type, self._handle_string)
            processed_value = handler(raw_value, rule)

            # 存储到 context 中
            if 'export_as' in rule:
                storage = self.context['global'] if rule.get('export_scope') == 'global' else self.context['sheets'][sheet_name]
                export_key = rule['export_as'].split('.')[-1]
                storage[export_key] = processed_value
            print(f"[DEBUG] 处理字段 {content_name}: {raw_value} → {processed_value}")
            return self._build_response(data_type, processed_value, rule, sheet_name, content_name)

        except Exception as e:
            print(f"处理失败 [{sheet_name}.{content_name}]: {str(e)}")
            return {'type': 'error', 'value': rule.get('default', '')}

    def _resolve_dependency(self, dep_key, current_sheet):
        """
        解析字段依赖关系，从上下文中获取已处理的值

        :param dep_key: 依赖字段名
        :param current_sheet: 当前工作表名称
        :return: 依赖字段的值
        :raises KeyError: 若未找到依赖项抛出异常
        """
        if '.' in dep_key:
            _, pure_key = dep_key.split('.', 1)
            if pure_key in self.context['sheets'][current_sheet]:
                return self.context['sheets'][current_sheet][pure_key]

        prefixed_key = f"{current_sheet}.{dep_key}"
        if prefixed_key in self.context['sheets'][current_sheet]:
            return self.context['sheets'][current_sheet][prefixed_key]
        if dep_key in self.context['sheets'][current_sheet]:
            return self.context['sheets'][current_sheet][dep_key]
        if dep_key in self.context['global']:
            return self.context['global'][dep_key]
        if '.' in dep_key:
            sheet_part, field_part = dep_key.split('.', 1)
            return self.context['sheets'][sheet_part].get(field_part)
        raise KeyError(f"未找到依赖项 {dep_key}（工作表：{current_sheet}）")

    def _build_response(self, data_type, value, rule, sheet, name):
        """
        构建统一响应结构

        :param data_type: 数据类型
        :param value: 处理后的值
        :param rule: 字段规则
        :param sheet: 所属工作表
        :param name: 字段名称
        :return: 包含元信息的响应字典
        """
        return {
            'type': data_type,
            'value': value,
            'meta': {
                'format': rule.get('format'),
                'target_cells': rule.get('target_cells'),
                'source_sheet': sheet,
                'source_field': name
            }
        }

    def _default_response(self, content_name):
        """
        构建默认响应（当找不到规则时）

        :param content_name: 内容名称
        :return: 默认响应对象
        """
        default_value = self.project_info.get(content_name, '待补充')
        return {
            'type': 'string',
            'value': default_value,
            'meta': {'is_default': True}
        }

    # 类型处理器 -----------------------------

    def _handle_string(self, value, rule):
        """
        字符串类型处理器

        :param value: 原始值
        :param rule: 字段规则
        :return: 字符串值
        """
        return str(value) if not pd.isnull(value) else rule.get('default', '')

    def _handle_date(self, value, rule):
        """
        日期类型处理器

        :param value: 原始值
        :param rule: 字段规则
        :return: 格式化后的日期字符串
        """
        fmt = rule.get('format', '%Y年%m月%d日')
        try:
            if isinstance(value, pd.Timestamp):
                return value.strftime(fmt)
            return pd.to_datetime(value).strftime(fmt)
        except:
            return rule.get('default', '日期格式错误')

    def _handle_list_vertical(self, value, rule):
        """
        纵向列表处理器（垂直方向填充）

        :param value: 原始值（可以是列表或单一值）
        :param rule: 字段规则
        :return: 截断后的列表
        """
        if not isinstance(value, (list, tuple)):
            return [value]
        return list(value)[:rule.get('max_items', 10)]

    def _handle_list_horizontal(self, value, rule):
        cells = rule.get('target_cells', [])
        if not cells:
            print("警告：横向列表未指定 target_cells")
            return []

        if not isinstance(value, (list, tuple)):
            value = [value]

        # 返回 (cell_ref, value) 元组列表
        return [(cells[i], val) for i, val in enumerate(value[:len(cells)])]


if __name__ == "__main__":
    # ProjectInfomation = {
    #     '施工单位': '浙江交工宏途交通建设有限公司',
    #     '监理单位': '浙江浙中建设工程管理有限公司',
    #     '单位工程': '路基工程',
    #     '分部工程': '涵洞、通道',
    #     '分项工程': '主体结构',
    #     '施工日期': '2024/05/31',
    #     '施工部位': 'K59+639圆管涵',
    #     '签字时间': '2024/05/31',
    #     '开工日期': '2024/05/01',
    #     '设计坐标(X,Y)': (3243273.926, 509154.842),
    #     '长': 44.5,
    #     '宽': 4,
    # }

    # 示例调用方式
    # df = pd.read_excel(r'C:\Users\Administrator\Desktop\工作常用程序\公路资料\检验批\static\template\模板数据.xlsx')
    # processor = DataProcessor(base_data=df, project_info=ProjectInfomation, rules=processing_rules)
    # enhanced_df = processor.process_dataframe(df)

    # # 获取结果
    # result = enhanced_df['processed_values']
    # print(result)
    from config.path import ProjectPathManager

    